#ifndef accountmanager_utils_account_h
#define accountmanager_utils_account_h

#include <utils/utils_decl.h>

#include <utils/bank.h>
#include <utils/person.h>
#include <utils/core/list.h>

namespace AccountManagerUtils {

//! Information about a bank account
/*!
 *  A bank account is uniquely identified by a name, an account number, a bank and a list of account owners
 */
class _accountmanager_utils_decl Account {

public:
	Account();
	Account(const Account& rhs);
	Account(const String& name, const String& number, const Bank* bank, const Person* owner);
	Account(const String& name, const String& number, const Bank* bank, const List<const Person*>& owners);
	~Account();
	Account& operator=(const Account& rhs);

	bool operator==(const Account& rhs) const;
	bool operator!=(const Account& rhs) const;

	String& name();
	const String& name() const;
	String& number();
	const String& number() const;
	void set_bank(const Bank* bank);
	const Bank* bank() const;
	List<const Person*>& owners();
	const List<const Person*>& owners() const;

private:
	String name_;
	String number_;
	const Bank* bank_;
	List<const Person*> owners_;
};

inline uint qHash(const Account& account) {
	uint res = qHash(account.name()) ^ qHash(account.number()) ^ qHash(*account.bank());
	for ( List<const Person*>::const_iterator it = account.owners().begin(); it != account.owners().end(); ++it ) {
		res ^= qHash(*(*it));
	}
	return res;
}

//===========================================================

//! Library of all bank accounts available on the current session
class _accountmanager_utils_decl AccountLib {

public:
	static const Account* find_account(const String& name, const String& number, const Bank* bank, List<const Person*>& owners);
	static const Set<Account>& accounts();
	
	~AccountLib();

private:
	AccountLib();

	static AccountLib* instance();

private:
	Set<Account> accounts_;
	static AccountLib* instance_;
};

} // namespace AccountManagerUtils

#endif
